package binpacking.main;

import binpacking.algorithms.*;
import binpacking.io.*;

public class Main {
	public static void main( String[] args ) {

		/* Create a file "random.txt" with 10000 Integers between 0 and 100 */
		new Randomizer(10000, 100, "src/binpacking/files/random.txt" );
		
		/* Set the just created file as source for the blocks */
		String blocksFile = "src/binpacking/files/random.txt";
		String binsFile = "src/binpacking/files/bins.txt";
		
		InputLoader inputLoader = new InputLoader( blocksFile, binsFile );

		// generate blocks and bins by files
		if( inputLoader.load() ) {
			// run algorithm with loaded data
			FirstFit firstFit = new FirstFit( inputLoader.getBlocks(), inputLoader.getBinContainer(), inputLoader.getBinSize() );
			long start = System.nanoTime();
			firstFit.doFirstFit();
			long end = System.nanoTime();
			System.out.println( "== First Fit ==" );
			printExecutionTime(start, end);
			System.out.println( firstFit.getResult() );
		}
		
		// generate blocks and bins by files
		if( inputLoader.load() ) {
			// run algorithm with loaded data
			FirstFitDecreasing firstFitDeceasing = new FirstFitDecreasing( inputLoader.getBlocks(), inputLoader.getBinContainer(), inputLoader.getBinSize() );
			long start = System.nanoTime();
			firstFitDeceasing.doFirstFitDecreasing();
			long end = System.nanoTime();
			System.out.println( "== First Fit Decreasing ==" );
			printExecutionTime(start, end);
			System.out.println( firstFitDeceasing.getResult() );
		}

		// generate blocks and bins by files
		if( inputLoader.load() ) {
			// run algorithm with loaded data
			BestFit bestFit = new BestFit( inputLoader.getBlocks(), inputLoader.getBinContainer(), inputLoader.getBinSize() );
			long start = System.nanoTime();
			bestFit.doBestFit();
			long end = System.nanoTime();
			System.out.println( "== Best Fit ==" );
			printExecutionTime(start, end);
			System.out.println( bestFit.getResult() );
		}

		// generate blocks and bins by files
		if( inputLoader.load() ) {
			// run algorithm with loaded data
			WorstFit worstFit = new WorstFit( inputLoader.getBlocks(), inputLoader.getBinContainer(), inputLoader.getBinSize() );
			long start = System.nanoTime();
			worstFit.doWorstFit();
			long end = System.nanoTime();
			System.out.println( "== Worst Fit ==" );
			printExecutionTime(start, end);
			System.out.println( worstFit.getResult() );
		}

		// generate blocks and bins by files
		if( inputLoader.load() ) {
			// run algorithm with loaded data
			AlmostWorstFit worstFit = new AlmostWorstFit( inputLoader.getBlocks(), inputLoader.getBinContainer(), inputLoader.getBinSize() );
			long start = System.nanoTime();
			worstFit.doWorstFit();
			long end = System.nanoTime();
			System.out.println( "== AlmostWorst Fit ==" );
			printExecutionTime(start, end);
			System.out.println( worstFit.getResult() );
		}

		// generate blocks and bins by files
		if( inputLoader.load() ) {
			// run algorithm with loaded data
			NextFit nextFit = new NextFit( inputLoader.getBlocks(), inputLoader.getBinContainer(), inputLoader.getBinSize() );
			long start = System.nanoTime();
			nextFit.run();
			long end = System.nanoTime();
			System.out.println( "== Next Fit ==" );
			printExecutionTime(start, end);
			System.out.println( nextFit.getResult() );
		}
		
		// generate blocks and bins by files
		if( inputLoader.load() ) {
			// run algorithm with loaded data
			LastFit lastFit = new LastFit( inputLoader.getBlocks(), inputLoader.getBinContainer(), inputLoader.getBinSize() );
			long start = System.nanoTime();
			lastFit.doLastFit();
			long end = System.nanoTime();
			System.out.println( "== Last Fit ==" );
			printExecutionTime(start, end);
			System.out.println( lastFit.getResult() );
		}
	}
	
	// ==============================================================
	// helper function for printing execution time in the right units
	// ==============================================================
	private static void printExecutionTime( long start, long end )	{
		long time = end - start;
		if ( time > 1000000000 )
			System.out.println( "executed in: " + ( time / 10000000 ) / 100.0 + " s"  );
		else if ( time > 1000000 )
			System.out.println( "executed in: " + ( time / 10000    ) / 100.0 + " ms" );
		else if ( time > 1000 )
			System.out.println( "executed in: " + ( time / 10       ) / 100.0 + " us" );
		else
			System.out.println( "executed in: " + ( time            )         + " ns" );
	}
}
